package com.gitee.huxing.framework.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.gitee.huxing.framework.core.module.RequestInfo;
import com.gitee.huxing.framework.core.module.ResponseInfo;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @Description:
 * @ProjectName: JavaCourse
 * @Package: com.gitee.huxing.framework.core
 * @ClassName: ServiceInvoker
 * @Author: huxing
 * @DateTime: 2021-09-30 下午3:46
 */
@Slf4j
public class ServiceInvoker {

    private ServiceResolver resolver;

    public ServiceInvoker(ServiceResolver resolver){
        this.resolver = resolver;
    }

    /**
     * @Description: 服务请求端方法执行
     * @Author: huxing
     * @param requestInfo 请求数据对象
     * @return com.gitee.huxing.framework.core.module.ResponseInfo
     * @Date: 2021/9/30 下午3:55
     **/
    public ResponseInfo invoke(RequestInfo requestInfo){
        // 请求业务对象
        ResponseInfo responseInfo = new ResponseInfo();
        // 请求的业务服务
        String serviceClass = requestInfo.getServiceClass();
        // 获取请求的业务对象
        Object service = resolver.reslove(serviceClass);
        try {
            // 获取方法对象
            Method method = this.resolveMethodFromClass(service.getClass(), requestInfo.getMethod());
            // TODO: 反射调用的时候，因为涉及到重载的问题，所以必须传入class的object对象以提供jvm确定方法
            Object result = method.invoke(service, requestInfo.getParams());
            // 返回结果
            responseInfo.setResult(JSON.toJSONString(result, SerializerFeature.WriteClassName));
            responseInfo.setStatus(true);
            log.info("返回的记录消息: {}",  responseInfo.getResult().toString());
            return responseInfo;
        } catch (IllegalAccessException | InvocationTargetException ex){
            ex.printStackTrace();
            responseInfo.setException(ex);
            responseInfo.setStatus(false);
            return responseInfo;
        }
    }

    /**
     * @Description: 根据方法名查询类中的方法对象
     * @Author: huxing
     * @param classz        类对象
     * @param methodName    方法名
     * @return java.lang.reflect.Method
     * @Date: 2021/9/30 下午3:52
     **/
    private Method resolveMethodFromClass(Class<?> classz, String methodName){
        return Arrays.stream(classz.getMethods())
                .filter(method -> methodName.equals(method.getName())).findFirst().get();
    }
}
